import os
from flask import Flask, render_template, jsonify, request
from datetime import datetime
from multiprocessing import Queue
import threading
from typing import Any, Dict, Union
from flask_cors import CORS
from utils.logger import Logger

# 创建 Web 服务器的日志记录器
web_logger = Logger('web_server')

app = Flask(__name__)
# 启用 CORS，允许所有来源
CORS(app, resources={
    r"/*": {
        "origins": "*",
        "methods": ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
        "allow_headers": ["Content-Type", "Authorization", "X-Requested-With"]
    }
})


def make_response(data: Any = None, message: str = "success", code: int = 0) -> Dict[str, Union[int, str, Any]]:
    """
    生成统一的API响应格式

    Args:
        data: 响应数据
        message: 响应消息
        code: 响应代码，0表示成功，非0表示错误

    Returns:
        Dict: 统一格式的响应字典
    """
    return {
        "code": code,
        "message": message,
        "data": data
    }


# 创建队列用于存储日志消息和通知
log_queue = Queue()
notification_queue = Queue()


def add_log_message(message: str):
    """添加日志消息到队列"""
    log_queue.put_nowait({
        'type': 'log',
        'data': {
            'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
            'message': message
        }
    })


# 全局变量用于存储服务状态
server_status = {
    'is_running': False,
    'messages': [],
    'notifications': [],
    'request_count': 0,
    'last_request_time': None,
    'port': 5000,
    'start_time': None
}


def update_server_status(running=True, port=None):
    """更新服务器状态"""
    global server_status
    server_status['is_running'] = running
    if port:
        server_status['port'] = port
    if running:
        server_status['start_time'] = datetime.now().strftime(
            '%Y-%m-%d %H:%M:%S')
    else:
        server_status['start_time'] = None


def is_port_in_use(port):
    """检查端口是否被占用"""
    import socket
    try:
        # 尝试连接端口
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
            s.settimeout(1)
            result = s.connect_ex(('127.0.0.1', port))
            return result == 0
    except:
        # 如果发生错误，假设端口被占用
        return True


def find_available_port(start_port=5000, max_port=5010):
    """查找可用端口"""
    for port in range(start_port, max_port + 1):
        if not is_port_in_use(port):
            return port
    return None


@app.before_request
def log_request_info():
    """记录请求信息"""
    try:
        server_status['request_count'] += 1
        server_status['last_request_time'] = datetime.now()

        log_data = {
            'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
            'method': request.method,
            'path': request.path,
            'remote_addr': request.remote_addr,
            'user_agent': request.headers.get('User-Agent', '未知'),
            'data': request.get_data(as_text=True) if request.is_json else None
        }

        # 使用 put_nowait 避免阻塞
        log_queue.put_nowait({
            'type': 'request',
            'data': log_data
        })
    except Exception as e:
        print(f"Error logging request: {str(e)}")  # 用于调试


@app.route('/')
def index():
    # 检测链接设备的IP地址
    client_ip = request.remote_addr
    # 检测链接设备的类型
    user_agent = request.headers.get('User-Agent', '未知')
    # 在 log_queue 中添加日志
    add_log_message(f"收到新请求 - IP: {client_ip}, 设备: {user_agent}")

    # 构建相对路径
    current_dir = os.path.dirname(__file__)
    html_path = os.path.join(
        current_dir, '..', 'resources', 'templates', 'index.html')
    # 从文件中读取HTML内容
    with open(html_path, 'r', encoding='utf-8') as f:
        html_content = f.read()
    return html_content


@app.route('/api/status')
def get_status():
    return jsonify(make_response(
        data=server_status,
        message="获取服务状态成功"
    ))


@app.route('/api/messages')
def get_messages():
    return jsonify(make_response(
        data=server_status['messages'],
        message="获取消息列表成功"
    ))

# 增加心跳检测路由


@app.route('/api/health', methods=['GET'])
def heartbeat():
    return jsonify(make_response(
        data={"status": "running"},
        message="服务运行中"
    ))


@app.route('/api/notifications', methods=['GET', 'POST'])
def handle_notifications():
    if request.method == 'POST':
        web_logger.info("收到新的通知 POST 请求")
        try:
            notification_data = request.get_json()
            if not notification_data:
                web_logger.error("收到无效的通知数据")
                return jsonify(make_response(
                    message="无效的通知数据",
                    code=400
                )), 400

            # 验证通知数据格式
            required_fields = ['title', 'message']
            if not all(field in notification_data for field in required_fields):
                return jsonify(make_response(
                    message="通知数据缺少必要字段 (title, message)",
                    code=400
                )), 400

            # 添加时间戳
            current_time = datetime.now()
            notification_data['timestamp'] = current_time.strftime(
                '%Y-%m-%d %H:%M:%S')

            # 将通知添加到状态列表
            server_status['notifications'].append(notification_data)

            # 记录通知日志
            try:
                add_log_message(
                    f"收到新通知 - {notification_data['title']}: {notification_data['message']}")
                print("已发送日志到队列")  # 调试输出
            except Exception as log_error:
                print(f"发送日志到队列失败: {str(log_error)}")  # 调试输出

            # 记录消息到服务器状态
            server_status['messages'].append({
                'timestamp': current_time.strftime('%Y-%m-%d %H:%M:%S'),
                'type': 'notification',
                'content': notification_data
            })

            # 发送通知到队列，触发声音提醒
            notification_queue.put_nowait({
                'type': 'notification',
                'data': notification_data
            })
            add_log_message("通知发送成功，已触发提示音")

            return jsonify(make_response(
                data=notification_data,
                message="通知发送成功"
            ))
        except Exception as e:
            return jsonify(make_response(
                message=f"处理通知时发生错误: {str(e)}",
                code=500
            )), 500
    else:
        return jsonify(make_response(
            data=server_status['notifications'],
            message="获取通知列表成功"
        ))


@app.route('/mobile-connect')
def mobile_connect():
    return jsonify(make_response(
        data={"connected": True},
        message="移动端连接成功"
    ))


def run_server(log_q=None, notification_q=None):
    global log_queue, notification_queue, server_status

    web_logger.info("开始初始化 Web 服务器")
    try:
        # 使用传入的队列替换全局队列
        if log_q:
            log_queue = log_q
            web_logger.debug("已设置日志队列")
        if notification_q:
            notification_queue = notification_q
            web_logger.debug("已设置通知队列")

        import multiprocessing
        # 确保在 Windows 下使用 spawn 方式创建进程
        if hasattr(multiprocessing, 'set_start_method'):
            try:
                multiprocessing.set_start_method('spawn')
            except RuntimeError:
                pass  # 如果已经设置了启动方法，忽略错误

        # 查找可用端口
        web_logger.info("正在查找可用端口...")
        available_port = find_available_port()
        if not available_port:
            web_logger.error("无法找到可用端口")
            raise Exception("无法找到可用端口")

        web_logger.info(f"找到可用端口: {available_port}")
        # 更新服务器状态
        update_server_status(running=True, port=available_port)

        # 记录启动日志
        startup_message = f"Flask 服务器正在启动 (端口: {available_port})..."

        # 验证端口是否确实可用
        if is_port_in_use(available_port):
            raise Exception(f"端口 {available_port} 已被占用")
        if log_queue:
            add_log_message(startup_message)

        print(startup_message)
        print("队列状态:", "log_queue=", log_queue is not None,
              "notification_queue=", notification_queue is not None)

        # 使用 werkzeug 服务器，添加更多配置选项
        from werkzeug.serving import run_simple
        # 确保服务器在所有网络接口上监听
        run_simple('0.0.0.0',
                   available_port,
                   app,
                   threaded=True,
                   use_reloader=False,  # 禁用重载器
                   use_debugger=False,  # 禁用调试器
                   use_evalex=False,    # 禁用交互式调试器
                   passthrough_errors=True)  # 允许错误传递到上层

    except Exception as e:
        error_message = f"服务器启动失败: {str(e)}"
        web_logger.error(f"服务器启动失败: {str(e)}", exc_info=True)
        print(error_message)
        if log_queue:
            add_log_message(error_message)
        update_server_status(running=False)
        raise


if __name__ == '__main__':
    run_server()
